package cn.hinglo.permission.common.generator;

import cn.hutool.core.util.StrUtil;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.plugin.hikaricp.HikariCpPlugin;
import com.jfinal.template.Engine;
import com.jfinal.template.Template;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @createTime: 2019/3/26 0026 9:09
 * @author: HingLo.C
 * @description: 用于Controller与Service的自动生成
 */
public class ControllerAndServiceGenerator {
    /***
     * 项目绝对路径,用于创建模板文件写入
     */
    private final static String basePath = "C:/Users/Administrator/Desktop/springbootbase/permission/src/main/java/";
    /**
     * generator工具包所在位置
     */
    private final static String generatorPath = "cn/hinglo/permission/common/generator/";
    /***
     * 设置基础包名称
     */
    private final static String basePackage = "cn.hinglo.permission.";
    /**
     * 数据库连接
     */
    private final static String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/permission_admin?useSSL=false&characterEncoding=utf8&serverTimezone=GMT";
    /***
     * 用户名
     */
    private final static String user = "root";
    /***
     * 密码
     */
    private final static String password = "root";

    /***
     * 实例化一个生成器对象
     */
    private static GeneratorBean generatorBean = new GeneratorBean(basePath, generatorPath, basePackage);


    public static void main(String[] args) throws IOException {

        // 类名称
        Engine engine = Engine.create("myEngine");
        engine.setDevMode(true);
        engine.setToClassPathSourceFactory();
        engine.addSharedMethod(new StrKit());

        // 第1步 创建实体bean
        String className = createJavaBean(engine, "core_permission", "core_");
        // 第2步创建controller
        createController(engine, className);
        // 第3步创建Service
        createService(engine, className);
        // 第四部创建Mapper
        createMapper(engine, className);


    }

    /**
     * 创建JavaBean
     *
     * @param engine       engine
     * @param tableName    表名称
     * @param removePrefix 移除的前缀
     * @return 返回结果
     * @throws IOException
     */
    private static String createJavaBean(Engine engine, String tableName, String removePrefix) throws IOException {
        // 第1步骤步创建普通JavaBean
        Map<String, Object> record = new Record().set("tableMeta", javaBean(tableName)).getColumns();
        Template template = engine.getTemplate(generatorBean.getBeanTemplate());
        String filePath = basePath + generatorBean.getBeanPackage().replace(".", "/");
        String className = StrUtil.upperFirst(StrUtil.toCamelCase(StrUtil.removePrefix(tableName, removePrefix)));
        record.put("fileName", "/" + className + ".java");
        record.put("filePath", filePath);
        record.put("packageName", generatorBean.getBeanPackage());
        record.put("className", className);
        String dataBean = template.renderToString(record);
        writeToFile(record, dataBean);
        return className;
    }

    /***
     * 创建controller
     * @param engine engine
     * @param className 实体名称
     * @throws IOException
     */
    private static void createController(Engine engine, String className) throws IOException {
        Map<String, Object> record = getInfo(1, className);
        Template template = engine.getTemplate(generatorBean.getControllerTemplate());
        String dataController = template.renderToString(record);
        writeToFile(record, dataController);

    }

    /***
     * 创建服务层方法
     * @param engine engine
     * @param className 实体名称
     * @throws IOException
     */
    private static void createService(Engine engine, String className) throws IOException {
        // 第3步创建Service
        Map<String, Object> record = getInfo(2, className);
        Template template = engine.getTemplate(generatorBean.getServiceTemplate());
        String dataService = template.renderToString(record);
        writeToFile(record, dataService);
    }

    /***
     * 创建服务层方法
     * @param engine engine
     * @param className 实体名称
     * @throws IOException
     */
    private static void createMapper(Engine engine, String className) throws IOException {
        // 第3步创建Service
        Map<String, Object> record = getInfo(3, className);
        Template template = engine.getTemplate(generatorBean.getMapperTemplate());
        String dataService = template.renderToString(record);
        writeToFile(record, dataService);
    }


    /***
     * 通过type 用来生成service与controller
     * @param type 1:controller 2 service
     * @param className 类名称
     * @return 返回封装好的Map信息
     */
    private static Map<String, Object> getInfo(int type, String className) {
        Map<String, Object> record = new HashMap<>(6);
        String packageName;
        String end;
        switch (type) {
            case 1:
                packageName = generatorBean.getControllerPackage();
                end = "Controller.java";
                break;
            case 2:
                packageName = generatorBean.getServicePackage();
                end = "Service.java";
                break;
            case 3:
                packageName = generatorBean.getMapperPackage();
                end = "Mapper.java";
                break;
            default:
                return record;
        }

        record.put("packageName", packageName);
        record.put("className", className);
        String filePath = basePath + packageName;
        filePath = filePath.replace(".", "/");
        String fileName = "/" + className + end;
        record.put("fileName", fileName);
        record.put("filePath", filePath);
        record.put("beanPackage", generatorBean.getBeanPackage());
        record.put("servicePackage", generatorBean.getServicePackage());
        record.put("mapperPackage", generatorBean.getMapperPackage());
        return record;
    }


    /**
     * 内容写入到文件总
     */
    private static void writeToFile(Map<String, Object> record, String data) throws IOException {
        String fileName = record.get("fileName").toString();
        String filePath = record.get("filePath").toString();
        File dir = new File(filePath);
        if (!dir.exists()) {
            boolean res = dir.mkdirs();
            if (!res) {
                throw new RuntimeException("文件夹创建失败,无法创建模板文件");
            }
        }
        try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath + fileName), StandardCharsets.UTF_8)) {
            osw.write(data);
        }
    }


    public static TableMeta javaBean(String tabelName) {
        MetaBuilder metaBuilder = new MetaBuilder(getDataSource());
        metaBuilder.setGenerateRemarks(true);
        List<TableMeta> tableMetas = metaBuilder.build();
        TableMeta tableMeta = null;
        for (TableMeta action : tableMetas) {
            if (tabelName.equals(action.name)) {
                tableMeta = action;
                break;
            }
        }
        return tableMeta;
    }

    private static HikariCpPlugin createDruidPlugin() {
        return new HikariCpPlugin(jdbcUrl,
                user,
                password);
    }

    private static DataSource getDataSource() {
        HikariCpPlugin druidPlugin = createDruidPlugin();
        druidPlugin.start();
        return druidPlugin.getDataSource();
    }
}
